package vcs

import (
	"fmt"
	"github.com/go-cmd/cmd"
	"io"
	"log"
	"mon-go/src/utils"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"time"
)

type JavaConfig struct {
	JarFullPath string
	WorkDir     string
	Env         string
}

func (javaConfig *JavaConfig) CopyJarToWorkDir() error {
	err := os.MkdirAll(javaConfig.WorkDir, os.ModePerm)
	if err != nil {
		return fmt.Errorf("无法创建目录: %v", err)
	}

	srcFile, err := os.Open(javaConfig.JarFullPath)
	if err != nil {
		return fmt.Errorf("无法打开源文件: %v", err)
	}
	defer srcFile.Close()

	// 获取源文件的文件名
	fileName := filepath.Base(javaConfig.JarFullPath)

	// 拼接目标文件路径
	dstFilePath := filepath.Join(javaConfig.WorkDir, fileName)

	// 创建目标文件
	dstFile, err := os.Create(dstFilePath)
	if err != nil {
		return fmt.Errorf("无法创建目标文件: %v", err)
	}
	defer dstFile.Close()

	// 执行拷贝
	_, err = io.Copy(dstFile, srcFile)
	if err != nil {
		return fmt.Errorf("文件拷贝失败: %v", err)
	}
	return nil
}

func (javaConfig *JavaConfig) StartJar(env string, module string, jarName string, forceKill string, enableLogging bool) error {
	return StartJar(javaConfig.JarFullPath, env, module, javaConfig.WorkDir, jarName, forceKill, enableLogging)
}

func StartJar(jarPath string, env string, module string, workDir string, jarName string, forceKill string, enableLogging bool) error {
	pid, _ := utils.GetJarPIDWithJPS(jarName)
	if pid > 0 {
		log.Printf("%s已经启动了,PID=%d,是否强杀:%s\n", jarName, pid, forceKill)
		if "true" == forceKill {
			err := utils.KillProcessByPID(pid)
			if err != nil {
				_ = fmt.Errorf("%s强杀失败,PID=%d,%v\n", jarName, pid, err)
				time.Sleep(5 * time.Second)
			} else {
				fmt.Printf("%s强杀成功\n", jarName)
				time.Sleep(5 * time.Second)
			}
		} else {
			return nil
		}
	}

	absJarPath, err := filepath.Abs(jarPath)
	if err != nil {
		log.Fatalf("无法解析 JAR 路径: %v", err)
	}
	jarPath = absJarPath

	if _, err := os.Stat(jarPath); os.IsNotExist(err) {
		log.Fatalf("JAR 文件不存在: %s", jarPath)
	}

	_, err = exec.LookPath("java")
	if err != nil {
		log.Fatalf("未找到 java 命令，请确保 JDK 已安装并配置 PATH: %v", err)
	}

	params := map[string]string{
		"-Dspring.profiles.active": env,
		"-Dlogging.file.name":      workDir + "/logs/" + module + ".log",
	}

	args := []string{"java"}
	for key, value := range params {
		args = append(args, key+"="+value)
	}
	args = append(args, "-jar", jarPath)

	if _, err := os.Getwd(); err == nil {
		//log.Printf("当前工作目录: %s", wd)
	}
	log.Printf("执行命令: %v,log=%v\n", args, enableLogging)

	command := cmd.NewCmdOptions(cmd.Options{
		Buffered:  false, // 不缓冲输出，确保进程独立运行
		Streaming: true,  // 启用流式输出以捕获错误
	}, args[0], args[1:]...)

	command.Dir = filepath.Dir(jarPath)
	log.Printf("设置工作目录: %s", command.Dir)

	go func() {
		for output := range command.Stdout {
			if enableLogging {
				fmt.Println(output)
			}
		}
		for errMsg := range command.Stderr {
			if enableLogging {
				fmt.Println(errMsg)
			}
		}
	}()

	statusChan := command.Start()

	select {
	case status := <-statusChan:
		if status.Error != nil {
			log.Fatalf("启动%s失败: %v", module, status.Error)
		}
		log.Printf("=====================%s已启动并在后台运行[PID=%d]=====================", module, status.PID)
	case <-time.After(5 * time.Second):
		//log.Println("等待进程状态超时，假设 JAR 已启动")
	}
	return nil
}

// StartJar 启动单个JAR文件
func StartJar1(jarPath string, env string, module string, workDir string, jarName string, forceKill string) error {
	// 检查是否已有进程运行
	pid, _ := utils.GetJarPIDWithJPS(jarName)
	if pid > 0 {
		log.Printf("[%s] 已经启动，PID=%d，是否强杀:%s", module, pid, forceKill)
		if forceKill == "true" {
			err := utils.KillProcessByPID(pid)
			if err != nil {
				log.Printf("[%s] 强杀失败，PID=%d，%v", module, pid, err)
				time.Sleep(5 * time.Second)
			} else {
				log.Printf("[%s] 强杀成功", module)
				time.Sleep(5 * time.Second)
			}
		} else {
			log.Printf("[%s] 跳过启动（进程已存在）", module)
			return nil
		}
	}

	// 获取JAR文件的绝对路径
	absJarPath, err := filepath.Abs(jarPath)
	if err != nil {
		return fmt.Errorf("[%s] 无法解析JAR路径 %s: %v", module, jarPath, err)
	}

	// 验证JAR文件是否存在
	if _, err := os.Stat(absJarPath); os.IsNotExist(err) {
		return fmt.Errorf("[%s] JAR文件不存在: %s", module, absJarPath)
	}
	log.Printf("[%s] JAR文件路径: %s", module, absJarPath)

	// 验证Java环境
	if _, err := exec.LookPath("java"); err != nil {
		return fmt.Errorf("[%s] 未找到java命令，请确保JDK已安装并配置PATH: %v", module, err)
	}

	// 确保日志目录存在
	logDir := filepath.Join(workDir, "logs")
	if err := os.MkdirAll(logDir, 0755); err != nil {
		return fmt.Errorf("[%s] 创建日志目录 %s 失败: %v", module, logDir, err)
	}

	// 构建启动参数
	params := map[string]string{
		"-Dspring.profiles.active": env,
		"-Dlogging.file.name":      filepath.Join(logDir, module+".log"),
	}

	args := []string{"java"}
	for key, value := range params {
		args = append(args, key+"="+value)
	}
	args = append(args, "-jar", absJarPath)

	// 适配Windows和Linux/Unix
	var command *cmd.Cmd
	if runtime.GOOS == "windows" {
		// Windows使用start /b启动后台进程
		args = append([]string{"/C", "start", "/b"}, args...)
		command = cmd.NewCmdOptions(cmd.Options{
			Buffered:  false,
			Streaming: false, // 禁用流式输出
		}, "cmd", args...)
	} else {

	}

	// 设置工作目录
	command.Dir = filepath.Dir(absJarPath)
	log.Printf("[%s] 设置工作目录: %s", module, command.Dir)

	// 启动命令
	start := command.Start()
	if start != nil {
		return fmt.Errorf("[%s] 启动失败: %v", module, start)
	}

	// 验证进程是否启动
	time.Sleep(2 * time.Second) // 等待进程初始化
	pid, _ = utils.GetJarPIDWithJPS(jarName)
	if pid <= 0 {
		return fmt.Errorf("[%s] 启动后未找到运行进程", module)
	}

	log.Printf("=====================[%s] 已启动并在后台运行 [PID=%d]=====================", module, pid)
	return nil
}
